home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr10 / inter35c.zip / INTPRINT.C < prev    next >
C/C++ Source or Header  |  1993-05-24  |  40KB  |  1,483 lines

  1. /************************************************************************/
  2. /* INTPRINT.C by Ralf Brown.  Donated to the Public Domain.        */
  3. /* Please do not remove my name from any copies or derivatives.        */
  4. /************************************************************************/
  5. /* Program History:                            */
  6. /*   v1.00  4/23/89  initial public release                */
  7. /*             with 4/30/89 list                    */
  8. /*   v1.10  5/21/89  added -I and -f                    */
  9. /*   v1.11  1/6/90   fixed #endif's for compilers which don't handle    */
  10. /*             labels                        */
  11. /*   v1.20  6/8/90   added -r                        */
  12. /*   v1.30  7/14/90  added -b, tables now stay aligned on odd indents    */
  13. /*   v1.40  10/6/90  added -B based on changes by Naoto Kimura, -w    */
  14. /*   v1.40a 5/6/91   HP LaserJet II support by Russ Herman        */
  15. /*   v1.41  7/9/91   HP PCL support by P.J.Farley III            */
  16. /*   v2.00  9/1/91   modular printer definitions            */
  17. /*             printing multipart interrupt list            */
  18. /*   v2.01  2/9/92   fixed summary entry for non-numeric AX= and AH=    */
  19. /*             smarter page breaks                */
  20. /*   v2.02  2/18/92  bugfix & isxdigit suggested by Aaron West        */
  21. /*   v2.10  3/14/92  updated to handle extra flags in headings        */
  22. /*   v2.11  5/23/92  bugfix pointed out by Joe White            */
  23. /*   v2.20  6/12/92  added -F based on code by Richard Brittain     */
  24. /*             added -H and Panasonic printer def by Lewis Paper    */
  25. /*   v2.21  10/14/92 fixed error in -H/-r interaction            */
  26. /*             updated for new 'Bitmask of' section        */
  27. /*   v2.22   2/15/93 exclude Index: by default, -x to force inclusion    */
  28. /*             changed 'Bitmask of' to 'Bitfields for'            */
  29. /*   v2.23   5/24/93 fix to allow INT/AL= to appear correctly in summary*/
  30. /************************************************************************/
  31. /* Recompiling:                                */
  32. /*   Turbo C / Borland C++                        */
  33. /*    tcc -mt -lt -Z -p intprint                    */
  34. /************************************************************************/
  35.  
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <ctype.h>
  39.  
  40. #define VERSION "2.23"
  41.  
  42. #ifdef __TURBOC__
  43. #  define PROTOTYPES
  44. #  include <stdlib.h>
  45.    int _Cdecl isatty(int handle) ;
  46.    void _setenvp(void) {} /* don't need the environment, so don't include it */
  47. #else
  48.  
  49. /* not Turbo C / Borland C, so set configuration #defines */
  50. #if 0  /* set to 1 if compiler supports ANSI-style prototypes, 0 otherwise */
  51. #define PROTOTYPES
  52. #endif
  53. #if 1  /* set to 0 if library contains strnicmp(), 1 otherwise */
  54. #define NEED_STRNICMP
  55. #endif
  56. #if 1  /* set to 0 if library contains isxdigit(), 1 otherwise */
  57. #define NEED_ISXDIGIT
  58. #endif
  59. #if 0  /* set to 0 if library contains strdup(), 1 otherwise */
  60. #define NEED_STRDUP
  61. #endif
  62. #if 1  /* set to 0 if library contains strupr(), 1 otherwise */
  63. #define NEED_STRUPR
  64. #endif
  65. #if 1  /* set to 0 if library contains three-arg itoa(), 1 otherwise */
  66. #define NEED_ITOA
  67. #endif
  68.  
  69. #define _Cdecl
  70.  
  71. #endif /* __TURBOC__ */
  72.  
  73. /***********************************************/
  74.  
  75. #ifndef FALSE
  76. #define FALSE 0
  77. #endif
  78. #ifndef TRUE
  79. #define TRUE !FALSE
  80. #endif
  81.  
  82. #define MAXLINE 81   /* at most 80 chars per line (plus newline) */
  83. #define MAXPAGE 200  /* at most 200 lines per page */
  84.  
  85. #define start_of_entry(s) (strncmp(s,"INT ",4) == 0)
  86.  
  87. /***********************************************/
  88.  
  89. typedef struct _cstr         /* a counted string */
  90.    {
  91.    int len ;             /* the string's length */
  92.    char *str ;             /* the actual contents of the string */
  93.    } cstr ;
  94.  
  95. #define CSTR(s) { sizeof(s)-1, (s) }  /* for defining a counted string literal */
  96. #define cstrlen(s) ((s)->len)     /* how long is the counted string? */
  97. #define cstrchar(s,i) ((s)->str[i])  /* retrieve a character from a counted string */
  98.  
  99. typedef struct _printer_def
  100.    {
  101.    char *name ;            /* for selecting the appropriate printer */
  102.    cstr init1, init2 ;        /* initialization strings */
  103.    cstr marginl, marginc, marginr ; /* margins: duplex even, non-duplex, duplex odd */
  104.    cstr duplex_on ;        /* turn on duplex mode */
  105.    cstr term1, term2 ;        /* cleanup strings */
  106.    cstr bold_on, bold_off ;    /* boldface on/off */
  107.    int indent ;            /* how many extra spaces to indent */
  108.    int lines_per_page ;        /* how many lines to print on each page */
  109.    int page_length ;        /* how many lines on each page */
  110.    int page_width ;        /* how many printable columns per line? */
  111. #ifdef PROTOTYPES
  112.    void (*put_line)(FILE *,int) ;/* function to call to print out divider line */
  113.    void (*set_typeface)(FILE *,char *) ;
  114. #else
  115.    void (*put_line)() ;        /* function to call to print out divider line */
  116.    void (*set_typeface)() ;
  117. #endif /* PROTOTYPES */
  118.    int *flag ;            /* flag to set when using this printer definition */
  119.    } PRINTER_DEF ;
  120.  
  121. struct filter_list
  122.    {
  123.    struct filter_list *next ;
  124.    char *str ;
  125.    } ;
  126.  
  127. typedef struct _header
  128.    {
  129.    int part ;
  130.    int first_on_page ; /* TRUE if a new entry starts at the top of the page */
  131.    char desc[24] ;
  132.    } HEADER ;
  133.  
  134. /***********************************************/
  135.  
  136. #ifdef PROTOTYPES
  137. void usage(void) ;
  138. void fatal(char *msg) ;
  139. void get_raw_line(char *buf,int size) ;
  140. int unwanted_section(char *buf) ;
  141. void get_line(char *buf,int size) ;
  142. void indent_line(FILE *fp) ;
  143. void indent_to(int where,FILE *fp) ;
  144. void put_line(FILE *fp, int len) ;
  145. void HPPCL_put_line(FILE *fp, int len) ;
  146. void HPPCL_set_typeface(FILE *fp,char *typeface) ;
  147. void fputcstr(cstr *s, FILE *fp) ;
  148. int divider_line(char *line) ;
  149. int section_start(char *line) ;
  150. int start_of_table(char *line) ;
  151. void output_line(char *line,FILE *fp) ;
  152. void fill_buffer(int lines, int lines_per_page) ;
  153. int find_page_break(int lines) ;
  154. void summarize(FILE *summary, int line, int pages_printed) ;
  155. void start_format(char *line) ;
  156. struct filter_list *add_filter_info(struct filter_list *list,char *str) ;
  157. void build_filter_lists(char *file) ;
  158. void print_line(char *line) ;
  159. void make_description(char *desc,int line) ;
  160. char *determine_heading(int last) ;
  161. void print_buffer(int last, int lines_per_page, int total_lines, int use_FF) ;
  162. void select_printer(char *name) ;
  163. void display_printers(void) ;
  164. int _Cdecl main(int argc, char **argv) ;
  165. #else
  166. void put_line() ;
  167. void HPPCL_put_line() ;
  168. #endif /* PROTOTYPES */
  169.  
  170. /***********************************************/
  171.  
  172. FILE *infile, *outfile ;
  173. char *input_file ;
  174.  
  175. char buffer[MAXPAGE][MAXLINE] ;
  176. char num[6] ;
  177. char summary_line[2*MAXLINE] ;
  178.  
  179. int pages_printed = 0 ;
  180. int page_width = 0 ;        /* page width in characters, 0 = use prtdef */
  181. int indent = 0 ;        /* number of blanks to add at start of each line */
  182. int widow_length = 10 ;        /* number of lines to scan for good place to break */
  183. int page_numbers = FALSE ;    /* add page numbers to bottom of page? */
  184. int multi_file = FALSE ;    /* printing multipart interrupt list? */
  185. int out_of_files = FALSE ;    /* hit end of last file for multipart printing? */
  186. int do_summary = FALSE ;    /* create a one-line-per-call summary? */
  187. int do_formats = FALSE ;    /* create a separate file with data structures? */
  188. int do_filter = FALSE ;        /* using a filtering file? */
  189. int do_headers = FALSE ;    /* add page headings? */
  190. int include_index_lines = FALSE ;
  191. int IBM_chars = FALSE ;        /* printer can handle IBM graphics characters */
  192. int boldface = FALSE ;        /* boldface titles and Return:/Notes: ? */
  193. int printer_bold = FALSE ;    /* boldface using printer control sequences? */
  194. int echo_format = FALSE ;
  195. int duplex = FALSE ;
  196. int HPPCL_mode = FALSE ;
  197. FILE *summary ;
  198. FILE *formats ;
  199. PRINTER_DEF *printer = NULL ;
  200.  
  201. int first_page = 0 ;
  202. int last_page = 29999 ;
  203.  
  204. struct filter_list *includes = NULL ;
  205. struct filter_list *excludes = NULL ;
  206.  
  207. HEADER header_first = { 0, FALSE, "" } ;
  208. HEADER header_last = { 0, FALSE, "" } ;
  209.  
  210. /***********************************************/
  211.  
  212. PRINTER_DEF printers[] =
  213.    {
  214.      { "default",
  215.        CSTR(""), CSTR(""),
  216.        CSTR(""), CSTR(""), CSTR(""),
  217.        CSTR(""),
  218.        CSTR(""), CSTR(""),
  219.        CSTR(""), CSTR(""),
  220.        -1,
  221.        60,
  222.        0,
  223.        79,
  224.        put_line,
  225.        NULL,
  226.        NULL,
  227.      },
  228.      { "Epson FX80, 12 cpi",
  229.        CSTR("\033M"), CSTR(""),
  230.        CSTR("\033l\004"), CSTR("\033l\007"), CSTR("\033l\014"),
  231.        CSTR(""),
  232.        CSTR("\033P"), CSTR("\033l\000"),
  233.        CSTR("\033E"), CSTR("\033F"),
  234.        0,
  235.        60,
  236.        0,
  237.        87,    /* 96 - left margin - 1 right margin */
  238.        put_line,
  239.        NULL,
  240.        NULL,
  241.      },
  242.      { "Panasonic KX-P1124i / 10 cpi Epson",
  243.        CSTR(""), CSTR(""),
  244.        CSTR(""), CSTR(""), CSTR(""),
  245.        CSTR(""),
  246.        CSTR(""), CSTR(""),
  247.        CSTR("\033E"), CSTR("\033F"),
  248.        -1,
  249.        60,
  250.        0,
  251.        79,
  252.        put_line,
  253.        NULL,
  254.        NULL,
  255.      },
  256.      { "HP PCL",
  257.        CSTR("\033(8U"), CSTR(""),
  258.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  259.        CSTR("\033&l1S"),
  260.        CSTR("\033E"), CSTR(""),
  261.        CSTR("\033(s3B"), CSTR("\033(s0B"),
  262.        0,
  263.        69,
  264.        0,
  265.        87,    /* 96 - left margin - 1 right margin */
  266.        HPPCL_put_line,
  267.        HPPCL_set_typeface,
  268.        &HPPCL_mode,
  269.      },
  270. #define HPPCL_FONT_ON_A "\033(s0p12h10v0s0b"
  271. /* HP PCL4/5 Font select: Roman-8;Upright12Pitch10PointMediumWeight */
  272. #define HPPCL_FONT_ON_B "T\033&l6.8571C"
  273. /* HP PCL4/5 Font select: End typeface select;VMI=7LPI: (48/7)-48th's inches*/
  274. #define HPPCL_IBM_LN_A    "\033&f0S\033*p-15Y\033*c"
  275. /* HP PCL4/5 IBM Line:    Push Pos;Up 15/720";Hor.Rule ???/300ths" long */
  276. #define HPPCL_IBM_LN_B    "a3b0P\033&f1S"
  277. /* HP PCL4/5 IBM Line:     3/300ths" high,Print rule;Pop Position */
  278.      { "LaserJet II",
  279.        CSTR("\033(10U"),CSTR(""),
  280.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  281.        CSTR(""),
  282.        CSTR("\033E"),CSTR(""),
  283.        CSTR("\033(s3B"),CSTR("\033(s0B"),
  284.        0,
  285.        54,
  286.        60,
  287.        79,
  288.        put_line,
  289.        NULL,
  290.        &IBM_chars,
  291.      },
  292.    } ;
  293. #define NUM_PRINTERS (sizeof(printers)/sizeof(printers[0]))
  294.  
  295. /***********************************************/
  296.  
  297. #ifdef NEED_STRNICMP
  298. #ifdef PROTOTYPES
  299. int strnicmp(char *s1,char *s2,int len)
  300. #else
  301. int strnicmp(s1,s2,len)
  302. char *s1,*s2 ;
  303. unsigned int len ;
  304. #endif PROTOTYPES
  305. {
  306.    char c1, c2 ;
  307.  
  308.    while (*s1 && *s2 && len > 0)
  309.       {
  310.       len-- ;
  311.       c1 = (islower(*s1) ? toupper(*s1) : *s1) ;
  312.       c2 = (islower(*s2) ? toupper(*s2) : *s2) ;
  313.       if (c1 != c2 || len == 0)     /* mismatch or substrings exhausted? */
  314.      return (c1 - c2) ;
  315.       s1++ ;
  316.       s2++ ;
  317.       }
  318.    return 0 ;  /* strings match exactly on first 'len' characters */
  319. }
  320. #endif /* NEED_STRNICMP */
  321.  
  322. #ifdef NEED_STRUPR
  323. #ifdef PROTOTYPES
  324. char *strupr(char *s)
  325. #else
  326. char *strupr(s)
  327. char *s ;
  328. #endif /* PROTOTYPES */
  329. {
  330.    char *orig_s = s ;
  331.    char c ;
  332.    
  333.    if (s)
  334.       while (*s)
  335.      {
  336.      c = *s ;      
  337.      *s++ = (islower(c) ? toupper(c) : c) ;
  338.      }
  339.    return orig_s ;
  340. }
  341. #endif /* NEED_STRUPR */
  342.  
  343. #ifdef NEED_STRDUP
  344. #ifdef PROTOTYPES
  345. char *strdup(char *s)
  346. #else
  347. char *strdup(s)
  348. char *s ;
  349. #endif /* PROTOTYPES */
  350. {
  351.    char *copy ;
  352.       
  353.    if (s)
  354.       copy = (char *)malloc(strlen(s)+1) ;
  355.    else
  356.       copy = NULL ;   
  357.    if (copy)
  358.       strcpy(copy,s) ;
  359.    return copy ;
  360. }
  361. #endif /* NEED_STRDUP */
  362.  
  363. #ifdef NEED_ISXDIGIT
  364. #ifdef PROTOTYPES
  365. int isxdigit(int c)
  366. #else
  367. int isxdigit(c)
  368. int c ;
  369. #endif /* PROTOTYPES */
  370. {
  371.    return isdigit(c) || (strchr("ABCDEFabcdef",c) != NULL) ;
  372. }
  373. #endif /* NEED_ISXDIGIT */
  374.  
  375. #ifdef NEED_ITOA
  376. #ifdef PROTOTYPES
  377. char *itoa(int num,char *buf,int radix)
  378. #else
  379. char *itoa(num,buf,radix)   /* not everybody has the same itoa() as TurboC */
  380. int num ;            /* minimal implementation */
  381. char *buf ;
  382. int radix ;
  383. #endif /* PROTOTYPES */
  384. {
  385.    int count = 0 ;
  386.    int i ; 
  387.    char tmp ;
  388.  
  389.    do {
  390.       buf[count++] = '0' + num % radix ;
  391.       num = num / radix ;
  392.    } while (num) ;
  393.    buf[count] = '\0' ;
  394.    if (count > 1)
  395.       for (i = 0 ; i < count / 2 ; i++)
  396.      {
  397.      tmp = buf[i] ;
  398.      buf[i] = buf[count-i-1] ;
  399.      buf[count-i-1] = tmp ;
  400.      }
  401.    return buf ;
  402. }
  403. #endif /* NEED_ITOA */
  404.  
  405. /***********************************************/
  406.  
  407. void usage()
  408. {
  409.    fputs("Usage: intprint [options] intlist [>|>>]output\n",stderr) ;
  410.    fputs("Options:\n",stderr) ;
  411.    fputs("\t-b\tboldface title lines and section headings\n",stderr) ;
  412.    fputs("\t-B\tboldface using printer control codes instead of overprinting\n",stderr) ;
  413.    fputs("\t-d\t(duplex) print even/odd pages with different indents\n",stderr) ;
  414.    fputs("\t-e\tassume 'elite' mode (96 chars per line) for default printer\n",stderr) ;
  415.    fputs("\t-ffile\twrite all data structure formats to 'file'\n",stderr) ;
  416.    fputs("\t-Ffile\tprint only entries matching filtering info in 'file'\n",stderr);
  417.    fputs("\t-H\tadd page headers showing interrupt call(s) on page\n",stderr) ;
  418.    fputs("\t-iN\tindent output N spaces (overridden by some printers)\n",stderr) ;
  419.    fputs("\t-I\tprinter supports IBM graphics characters\n",stderr) ;
  420.    fputs("\t-lN\tprint N lines per page (default depends on printer)\n",stderr) ;
  421.    fputs("\t-LN\tassume N lines on a page, use linefeeds if > #lines printed\n",stderr) ;
  422.    fputs("\t-m\tlist is in multiple parts starting with the named file\n",stderr) ;
  423.    fputs("\t-nN\tassume N pages have been printed from previous parts\n",stderr) ;
  424.    fputs("\t-p\tadd page numbers\n",stderr) ;
  425.    fputs("\t-Pname\tassume printer 'name' (-P? lists supported printers)\n",stderr) ;
  426.    fputs("\t-rN:M\tprint only pages N through M\n",stderr) ;
  427.    fputs("\t-sfile\twrite a one-line-per-function summary to 'file'\n",stderr) ;
  428.    fputs("\t-tN\tselect typeface N for the chosen printer\n",stderr) ;
  429.    fputs("\t-wN\tscan N lines from bottom of page for good place to break\n",stderr) ;
  430.    fputs("\t-x\tinclude Index: lines in formatted output\n",stderr) ;
  431.    exit(1) ;
  432. }
  433.  
  434. /***********************************************/
  435.  
  436. void fatal(msg)
  437. char *msg ;
  438. {
  439.    fputs(msg,stderr) ;
  440.    fputs("\n",stderr) ;
  441.    exit(1) ;
  442. }
  443.  
  444. /***********************************************/
  445.  
  446. void indent_line(fp)
  447. FILE *fp ;
  448. {
  449.    int ind = indent ;
  450.  
  451.    while (ind >= 8)
  452.       {
  453.       fputc('\t',fp) ;
  454.       ind -= 8 ;
  455.       }
  456.    while (ind-- > 0)
  457.       fputc(' ', fp) ;
  458. }
  459.  
  460. /***********************************************/
  461.  
  462. void indent_to(where,fp)
  463. int where ;
  464. FILE *fp ;
  465. {
  466.    indent_line(fp) ;
  467.    while (where-- > 0)
  468.       fputc(' ', fp) ;
  469. }
  470.  
  471. /***********************************************/
  472.  
  473. void put_line(fp,len)
  474. FILE *fp ;
  475. int len ;
  476. {
  477.    int i ;
  478.  
  479.    if (IBM_chars)
  480.       for (i = 0 ; i < len ; i++)
  481.      fputc(196,fp) ;  /* single horizontal line */
  482.    else
  483.       for (i = 0 ; i < len ; i++)
  484.      fputc('-',fp) ;
  485. }
  486.  
  487. /***********************************************/
  488.  
  489. void HPPCL_put_line(fp,len)
  490. FILE *fp ;
  491. int len ;
  492. {
  493.    fputs(HPPCL_IBM_LN_A,fp) ;
  494.    itoa((len * 25), num, 10) ;
  495.    fputs(num,fp) ;
  496.    fputs(HPPCL_IBM_LN_B,fp) ;
  497. }
  498.  
  499. /***********************************************/
  500.  
  501. void HPPCL_set_typeface(fp,typeface)
  502. FILE *fp ;
  503. char *typeface ;
  504. {
  505.    fputs(HPPCL_FONT_ON_A,fp) ;
  506.    if (typeface)
  507.       fputs(typeface,fp) ;
  508.    else
  509.       fputs("8",fp) ;
  510.    fputs(HPPCL_FONT_ON_B,fp) ;
  511. }
  512.  
  513. /***********************************************/
  514.  
  515. void fputcstr(s,fp)        /* output the counted string to the given file */
  516. FILE *fp ;
  517. cstr *s ;
  518. {
  519.    int i ;
  520.  
  521.    for (i = 0 ; i < cstrlen(s) ; i++)
  522.       fputc(cstrchar(s,i),fp) ;
  523. }
  524.  
  525. /***********************************************/
  526.  
  527. int divider_line(line)
  528. char *line ;
  529. {
  530.    return strncmp(line,"--------",8) == 0 ;
  531. }
  532.  
  533. /***********************************************/
  534.  
  535. int section_start(line)
  536. char *line ;
  537. {
  538.    return (strncmp(line,"Return:",7) == 0 ||
  539.        strncmp(line,"Desc:",5) == 0 ||
  540.        strncmp(line,"Note:",5) == 0 ||
  541.        strncmp(line,"Notes:",6) == 0 ||
  542.        strncmp(line,"SeeAlso:",8) == 0 ||
  543.        strncmp(line,"BUG:",4) == 0 ||
  544.            strncmp(line,"BUGS:",5) == 0 ||
  545.        strncmp(line,"Program:",8) == 0 ||
  546.        strncmp(line,"Index:",6) == 0
  547.       ) ;
  548. }
  549.  
  550. /***********************************************/
  551.  
  552. int start_of_table(line)
  553. char *line ;
  554. {
  555.    return (strncmp(line,"Format of ",10) == 0 ||
  556.            strncmp(line,"Values ",7) == 0 ||
  557.            strncmp(line,"Call ",5) == 0 ||
  558.        strncmp(line,"Bitfields for ",14) == 0
  559.           ) ;
  560. }
  561.    
  562. /***********************************************/
  563.  
  564. void output_line(line,fp)
  565. char *line ;
  566. FILE *fp ;
  567. {
  568.    int pos = 0 ;
  569.    char bold[10] ;
  570.  
  571.    if (boldface)
  572.       {
  573.       if (start_of_entry(line) || start_of_table(line))
  574.      {
  575.      indent_line(fp) ;
  576.      if (printer_bold)
  577.         {
  578.         fputcstr(&printer->bold_on,fp) ;
  579.         fputs(line,fp) ;
  580.         fputcstr(&printer->bold_off,fp) ;
  581.         line = NULL ;
  582.         }
  583.      else
  584.         {
  585.         fputs(line,fp) ;
  586.         fputc('\r',fp) ;
  587.         }
  588.      }
  589.       else if (section_start(line))
  590.      {
  591.      strncpy(bold,line,sizeof bold) ;
  592.      *strchr(bold,':') = '\0' ;
  593.      indent_line(fp) ;
  594.      if (printer_bold)
  595.         {
  596.         fputcstr(&printer->bold_on,fp) ;
  597.         fputs(bold,fp) ;
  598.         fputcstr(&printer->bold_off,fp) ;
  599.         pos = strlen(bold) ;     /* we're no longer at the left edge of the */
  600.         line += pos ;         /* line, so figure out where we are */
  601.         }
  602.      else
  603.         {
  604.         fputs(bold,fp) ;
  605.         fputc('\r',fp) ;
  606.         }
  607.      }
  608.       } /* boldface */
  609.    if (line && *line)
  610.       {
  611.       if (pos == 0)        /* are we currently at the left edge of the line? */
  612.      indent_line(fp) ;  /* if yes, indent the desired amount */
  613.       if (indent % 8)
  614.      {
  615.      while (*line)
  616.         {
  617.         if (*line == '\t')
  618.            do {
  619.           fputc(' ',fp) ;
  620.           } while (++pos % 8) ;
  621.         else
  622.            {
  623.            fputc(*line,fp) ;
  624.            pos++ ;
  625.            }
  626.         line++ ;
  627.         }
  628.      }
  629.       else
  630.      fputs(line,fp) ;
  631.       }
  632.    fputc('\n',fp) ;
  633. }
  634.  
  635. /***********************************************/
  636.  
  637. void get_raw_line(buf,size)
  638. char *buf ;
  639. int size ;
  640. {
  641.    int last ;
  642.  
  643.    buf[0] = '\0' ;
  644.    if (out_of_files)
  645.       return ;
  646.    fgets(buf,size,infile) ;
  647.    if ((feof(infile) || buf[0] == '\0'))
  648.       if (multi_file)
  649.      {
  650.      FILE *tempfile ;
  651.  
  652.      last = strlen(input_file) - 1 ;
  653.      input_file[last]++ ;
  654.      if ((tempfile = fopen(input_file,"r")) != NULL)
  655.         {
  656.         fclose(infile) ;
  657.         infile = tempfile ;
  658.         fgets(buf,size,infile) ;
  659.         }
  660.      else
  661.         {
  662.         out_of_files = TRUE ;
  663.         return ;
  664.         }
  665.      }
  666.       else
  667.      out_of_files = TRUE ;
  668.    last = strlen(buf) - 1 ;
  669.    while (last >= 0 && (buf[last] == '\n' || buf[last] == '\r'))
  670.       buf[last--] = '\0' ;
  671. }
  672.  
  673. /***********************************************/
  674.  
  675. int unwanted_section(buf)
  676. char *buf ;
  677. {
  678.    int unwanted = FALSE ;
  679.    int found ;
  680.    char str[MAXLINE] ;
  681.    struct filter_list *p ;
  682.    
  683.    if (start_of_entry(buf)) /* is it an interrupt entry? */
  684.       {
  685.       strncpy(str,buf,sizeof str) ;
  686.       str[sizeof str - 1] = '\0' ;
  687.       (void) strupr(str) ;
  688.       /* set 'unwanted' to TRUE if *any* exclude string matches */
  689.       for (p = excludes ; p ; p = p->next)
  690.      {
  691.      if (p->str && strstr(str, p->str) != NULL)
  692.         {
  693.         unwanted = TRUE ;
  694.         break ;
  695.         }
  696.      }
  697.       /* if still wanted, set to TRUE if *no* include string matches */
  698.       if (!unwanted)
  699.      {
  700.      found = FALSE ;
  701.      for (p = includes ; p ; p = p->next)
  702.         {
  703.         if (p->str && strstr(str, p->str) != NULL)
  704.            {
  705.            found = TRUE ;
  706.            break ; 
  707.            }
  708.         }
  709.      if (!found)
  710.         unwanted = TRUE ;
  711.      }
  712.       }
  713.    return unwanted ;
  714. }
  715.  
  716. /***********************************************/
  717.  
  718. void get_line(buf,size)
  719. char *buf ;
  720. int size ;
  721. {
  722.    static char next_line[MAXLINE] ;
  723.    static int readahead = FALSE ;
  724.  
  725.    /* get the next line from the file, skipping unwanted entries */
  726.    if (readahead)
  727.       {
  728.       strncpy(buf,next_line,size) ;
  729.       buf[size-1] = '\0' ;
  730.       readahead = FALSE ;
  731.       }
  732.    else
  733.       {
  734.       do {
  735.      get_raw_line(buf,size) ;
  736.      } while (!include_index_lines && strncmp(buf,"Index:",6) == 0) ;
  737.       strncpy(next_line,buf,sizeof next_line);
  738.       next_line[sizeof next_line - 1] = '\0' ;
  739.       /* if we read a divider line, we have to look ahead */
  740.       while (do_filter && next_line[0] && divider_line(next_line))
  741.      {
  742.      strncpy(buf,next_line,size) ; /* we may be returning the divider */
  743.      buf[size-1] = '\0' ;
  744.      get_raw_line(next_line,sizeof next_line) ;
  745.      if (unwanted_section(next_line))
  746.         {
  747.         while (!divider_line(next_line))
  748.            get_raw_line(next_line,sizeof next_line) ;
  749.         }
  750.      else /* section is wanted, so return divider and then next line */
  751.         readahead = TRUE ;
  752.      }
  753.       }
  754. }
  755.  
  756. /***********************************************/
  757.  
  758. void fill_buffer(lines,lines_per_page)
  759. int lines, lines_per_page ;
  760. {
  761.    int i ;
  762.  
  763.    if (lines)
  764.       for (i = lines ; i < lines_per_page ; i++)
  765.      strcpy(buffer[i-lines], buffer[i]) ;
  766.    else
  767.       lines = lines_per_page ;
  768.    for (i = lines_per_page - lines ; i < lines_per_page ; i++)
  769.       get_line(buffer[i], sizeof(buffer[i])) ;
  770. }
  771.  
  772. /***********************************************/
  773.  
  774. int find_page_break(lines)
  775. int lines ;
  776. {
  777.    int i ;
  778.  
  779.    for (i = 0 ; i < widow_length ; i++)
  780.       {
  781.       if (strcmp(buffer[lines-i-1],"\n") == 0 ||
  782.       strlen(buffer[lines-i-1]) == 0 ||
  783.       divider_line(buffer[lines-i-1]) ||
  784.       section_start(buffer[lines-i]))
  785.      return lines - i ;
  786.       }
  787.    return lines ;
  788. }
  789.  
  790. /***********************************************/
  791.  
  792. void summarize(summary, line, pages_printed)
  793. FILE *summary ;
  794. int line, pages_printed ;
  795. {
  796.    char *s, reg ;
  797.    int i ;
  798.    int max_descrip ;
  799.    int len ;
  800.  
  801.    s = buffer[line] ;
  802.    if (start_of_entry(s))
  803.       {
  804.       strcpy(summary_line," -- -- -- ") ;
  805.       summary_line[1] = s[4] ;     /* output interrupt number */
  806.       summary_line[2] = s[5] ;
  807.       len = 4 ;
  808.       s = buffer[line+1] ;
  809.       while (*s && isspace(*s))
  810.      s++ ;
  811.       if (*s == 'A')
  812.      {
  813.      reg = s[1] ;
  814.      while (*s && *s != '=')
  815.         s++ ;
  816.      s++ ;        /* skip the equal sign */
  817.      while (*s && isspace(*s))
  818.         s++ ;    /* skip the space between equal sign and number */
  819.      if (isxdigit(*s) && isxdigit(s[1]))
  820.         {
  821.         if (reg == 'L')
  822.            len += 3 ;
  823.         summary_line[len++] = *s++ ;
  824.         summary_line[len++] = *s++ ;
  825.         if (reg == 'X')
  826.            {
  827.            len++ ;
  828.            summary_line[len++] = *s++ ;
  829.            summary_line[len] = *s ;
  830.            }
  831.         }
  832.      }
  833.       len = 10 ;
  834.       if (page_numbers)
  835.      {
  836.      itoa(pages_printed,num,10) ;
  837.      for (i = strlen(num) ; i < 3 ; i++)
  838.         summary_line[len++] = ' ' ;
  839.      strcpy(summary_line+len,num) ;
  840.      len += strlen(num) ;
  841.      summary_line[len++] = ' ' ;
  842.      }
  843.       s = buffer[line] + 7 ;    /* find function description */
  844.       if (*s && *s != '-')    /* does the heading contain flags? */
  845.      {
  846.      while (*s && !isspace(*s))
  847.         summary_line[len++] = *s++ ;
  848.      summary_line[len++] = '>' ;
  849.      summary_line[len++] = ' ' ;
  850.      while (*s && *s != '-')
  851.         s++ ;
  852.      }
  853.       while (*s && !isspace(*s))
  854.      s++ ;
  855.       while (*s && isspace(*s))
  856.      s++ ;
  857.       max_descrip = (page_width > sizeof(summary_line)-1) ? 
  858.                    sizeof(summary_line)-1 : page_width ;
  859.       while (len < max_descrip && *s)
  860.      summary_line[len++] = *s++ ;
  861.       summary_line[len] = '\0' ;
  862.       if (do_summary && summary)
  863.      output_line(summary_line,summary) ;
  864.       }
  865. }
  866.  
  867. /***********************************************/
  868.  
  869. void start_format(line)
  870. char *line ;
  871. {
  872.    indent_line(formats) ;
  873.    (*printer->put_line)(formats,79) ;
  874.    fputc('\n',formats) ;
  875.    indent_line(formats) ;
  876.    fputs(summary_line,formats) ;
  877.    fputc('\n',formats) ;
  878.    indent_line(formats) ;
  879.    fputc('\t',formats) ;
  880.    fputs(line+10,formats) ;
  881.    fputc('\n',formats) ;
  882.    echo_format = TRUE ;
  883. }
  884.  
  885. /***********************************************/
  886.  
  887. void print_line(line)
  888. char *line ;
  889. {
  890.    if (*line)
  891.       {
  892.       if (divider_line(line))
  893.      {
  894.      indent_line(outfile) ;
  895.      (*printer->put_line)(outfile,79) ;
  896.      fputc('\n', outfile) ;
  897.      echo_format = FALSE ;
  898.      }
  899.       else
  900.      {
  901.      output_line(line, outfile) ;
  902.      if (echo_format)
  903.         output_line(line,formats) ;
  904.      }
  905.       }
  906.    else
  907.       {
  908.       fputc('\n', outfile) ;
  909.       echo_format = FALSE ;
  910.       }
  911. }
  912.  
  913. /***********************************************/
  914.  
  915. void make_description(desc,line)
  916. char *desc ;
  917. int line ;
  918. {
  919.    summarize(NULL,line,0) ;
  920.    memcpy(desc,"INT ", 4) ;
  921.    desc += 4 ;
  922.    *desc++ = summary_line[1] ;
  923.    *desc++ = summary_line[2] ;
  924.    if (summary_line[4] != '-')
  925.       {
  926.       memcpy(desc,", AH=", 5) ;
  927.       desc += 5 ;
  928.       *desc++ = summary_line[4] ;
  929.       *desc++ = summary_line[5] ;
  930.       }
  931.    if (summary_line[7] != '-')
  932.       {
  933.       memcpy(desc,", AL=", 5) ;
  934.       desc += 5 ;
  935.       *desc++ = summary_line[7] ;
  936.       *desc++ = summary_line[8] ;
  937.       }
  938.    *desc = '\0' ;
  939. }
  940.  
  941. /***********************************************/
  942.  
  943. char *determine_heading(last)
  944. int last ;
  945. {
  946.    int i ;
  947.    char *heading ;
  948.    char num[10] ;
  949.    
  950.    if (start_of_entry(buffer[0]))
  951.       {
  952.       make_description(header_first.desc,0) ;
  953.       header_first.part = 1 ;
  954.       header_first.first_on_page = TRUE ;
  955.       }
  956.    else if (header_last.part == 0)  /* very first entry? */
  957.       {
  958.       for (i = 0 ; i < last ; i++)
  959.      if (start_of_entry(buffer[i]))
  960.         {
  961.         make_description(header_first.desc,i) ;
  962.         header_first.part = 1 ;
  963.         header_first.first_on_page = TRUE ;
  964.         break ;
  965.         }
  966.       }
  967.    else
  968.       {
  969.       strcpy(header_first.desc,header_last.desc) ;
  970.       header_first.part = header_last.part + 1 ;
  971.       header_first.first_on_page = FALSE ;
  972.       }
  973.    /* assume entry spans entire page */
  974.    strcpy(header_last.desc,header_first.desc) ;
  975.    header_last.part = header_first.part ;
  976.    header_last.first_on_page = header_first.first_on_page ;
  977.    /* find last entry on page */
  978.    if (header_first.part > 0)
  979.       {
  980.       if ((heading = calloc(1,MAXLINE)) == NULL)
  981.          return NULL ;
  982.       for (i = last-1 ; i > 0 ; i--)
  983.      if (start_of_entry(buffer[i]))
  984.         {
  985.         make_description(header_last.desc,i) ;
  986.         header_last.part = 1 ;
  987.         header_last.first_on_page = FALSE ;
  988.         break ;
  989.         }
  990.       strcpy(heading,header_first.desc) ;
  991.       if (header_first.part > 1)
  992.      {
  993.      strcat(heading," (Part ") ;
  994.      itoa(header_first.part,num,10) ;
  995.      strcat(heading,num) ;
  996.      strcat(heading,")") ;
  997.      }
  998.       if (strcmp(header_first.desc,header_last.desc) != 0 ||
  999.       header_first.part != header_last.part)
  1000.      {
  1001.      strcat(heading," to ") ;
  1002.      strcat(heading,header_last.desc) ;
  1003.      if (header_last.part > 1)
  1004.         {
  1005.         strcat(heading," (Part ") ;
  1006.         itoa(header_last.part,num,10) ;
  1007.         strcat(heading,num) ;
  1008.         strcat(heading,")") ;
  1009.         }
  1010.      }
  1011.       return heading ; 
  1012.       }
  1013.    else /* no headings yet */
  1014.       return NULL ;
  1015. }
  1016.  
  1017. /***********************************************/
  1018.  
  1019. void print_buffer(last,lines_per_page,total_lines,use_FF)
  1020. int last, lines_per_page, total_lines ;
  1021. int use_FF ;
  1022. {
  1023.    int i ;
  1024.  
  1025.    pages_printed++ ;
  1026.    if (do_headers)
  1027.       {
  1028.       char *heading ;
  1029.       
  1030.       if ((heading = determine_heading(last)) != NULL)
  1031.      {
  1032.      if (pages_printed >= first_page && pages_printed <= last_page)
  1033.         {
  1034.         indent_to(40-strlen(heading)/2,outfile) ;
  1035.         if (boldface)
  1036.            {
  1037.            if (printer_bold)
  1038.           {
  1039.           fputcstr(&printer->bold_on,outfile) ;
  1040.           fputs(heading,outfile) ;
  1041.           fputcstr(&printer->bold_off,outfile) ;
  1042.           }
  1043.            else
  1044.           {
  1045.           fputs(heading,outfile) ;
  1046.           fputc('\r',outfile) ;
  1047.           indent_to(40-strlen(heading)/2,outfile) ;
  1048.           fputs(heading,outfile) ;
  1049.           }
  1050.            }
  1051.         else
  1052.            fputs(heading,outfile) ;
  1053.         }
  1054.      free(heading) ;
  1055.      }
  1056.       fputs("\n\n",outfile) ;
  1057.       }
  1058.    for (i = 0 ; i < last ; i++)
  1059.       {
  1060.       if (pages_printed >= first_page && pages_printed <= last_page)
  1061.      print_line(buffer[i]) ;
  1062.       if (do_summary || do_formats)  /* need summary lines if doing formats */
  1063.      summarize(summary,i,pages_printed) ;
  1064.       if (do_formats && strncmp(buffer[i],"Format of ",10) == 0)
  1065.      start_format(buffer[i]) ;
  1066.       }
  1067.    if (pages_printed >= first_page && pages_printed <= last_page)
  1068.       {
  1069.       if (page_numbers)
  1070.      {
  1071.      for (i = last ; i < lines_per_page - 1 ; i++)
  1072.         fputc('\n', outfile) ;
  1073.      indent_to(38,outfile) ;
  1074.      fputs("- ", outfile) ;
  1075.      itoa(pages_printed, num, 10) ;
  1076.      fputs(num, outfile) ;
  1077.      fputs(" -\n", outfile) ;
  1078.      }
  1079.       if (use_FF)
  1080.      fputc('\f', outfile) ;
  1081.       else
  1082.      for (i = page_numbers?lines_per_page:last ; i<total_lines ; i++)
  1083.         fputc('\n', outfile) ;
  1084.       if (duplex)
  1085.      {
  1086.      if ((pages_printed % 2) == 1)    /* next page even or odd? */
  1087.         fputcstr(&printer->marginl, outfile) ;    /* even page */
  1088.      else
  1089.         fputcstr(&printer->marginr, outfile) ;    /* odd page */
  1090.      }
  1091.       }
  1092. }
  1093.  
  1094. /***********************************************/
  1095.  
  1096. void display_printers()
  1097. {
  1098.    int i ;
  1099.    
  1100.    fputs("Valid printer names are:\n",stderr) ;
  1101.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  1102.       {
  1103.       fputc('\t',stderr) ;
  1104.       fputs(printers[i].name,stderr) ;
  1105.       fputc('\n',stderr) ;
  1106.       }
  1107.    fputs("When entering the printer name, use either a dash or an underscore\n",stderr) ;
  1108.    fputs("in place of blanks.  Case is ignored, and the name may be abbreviated\n",stderr) ;
  1109.    fputs("to the shortest unique prefix.\n",stderr) ;
  1110.    exit(1) ;
  1111. }
  1112.  
  1113. /***********************************************/
  1114.  
  1115. void select_printer(name)
  1116. char *name ;
  1117. {
  1118.    int i, len, prt = -1 ;
  1119.    
  1120.    len = strlen(name) ;
  1121.    for (i = 0 ; i < len ; i++)        /* convert dashes and underscores to blanks */
  1122.       if (name[i] == '-' || name[i] == '_')
  1123.      name[i] = ' ' ;
  1124.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  1125.       if (strnicmp(name,printers[i].name,strlen(name)) == 0)
  1126.      if (prt == -1)
  1127.         prt = i ;
  1128.      else
  1129.         fatal("Ambiguous printer name!  Use -P? to list printers.") ;
  1130.    if (prt == -1)
  1131.       fatal("Unknown printer name!  Use -P? to list printers.") ;
  1132.    else
  1133.       printer = &printers[prt] ;
  1134. }
  1135.  
  1136. /***********************************************/
  1137.  
  1138. struct filter_list *add_filter_info(list,str)
  1139. struct filter_list *list ;
  1140. char *str ;
  1141. {
  1142.    struct filter_list *new ;
  1143.    
  1144.    if ((new = (struct filter_list *)calloc(1,sizeof(struct filter_list))) != NULL)
  1145.       {
  1146.       new->next = list ;
  1147.       new->str = strupr(strdup(str)) ;
  1148.       if (new->str == NULL)
  1149.      new = NULL ;
  1150.       }
  1151.    if (new == NULL)
  1152.       {
  1153.       fputs("Error: out of memory\n",stderr) ;
  1154.       exit(1) ;
  1155.       }
  1156.    return new ;
  1157. }
  1158.  
  1159. /***********************************************/
  1160.  
  1161. void build_filter_lists(file)
  1162. char *file ;
  1163. {
  1164.    FILE *fp ;
  1165.    char buf[MAXLINE] ;
  1166.    int len ;
  1167.    
  1168.    if ((fp = fopen(file,"r")) == NULL)
  1169.       {
  1170.       fputs("Warning: unable to open filtering file, will print entire list.\n",stderr) ;
  1171.       do_filter = FALSE ;
  1172.       }
  1173.    else /* OK, file is open, so start reading */
  1174.       {
  1175.       while (!feof(fp))
  1176.      {
  1177.      buf[0] = '\0' ;
  1178.      if (fgets(buf, sizeof(buf), fp) == NULL)
  1179.         {
  1180.         if (!feof(fp)) /* was it an error other than EOF? */
  1181.            fputs("Warning: error reading filtering data, filtering may be incomplete.\n",stderr) ;
  1182.         break ;
  1183.         }
  1184.      len = strlen(buf) ;
  1185.      if (len > 0 && buf[len-1] == '\n')
  1186.         buf[--len] = '\0' ;
  1187.      if (len > 1)
  1188.         {
  1189.         switch (buf[0])
  1190.            {
  1191.            case '+':
  1192.           includes = add_filter_info(includes,buf+1) ;
  1193.           break ;
  1194.            case '-':
  1195.           excludes = add_filter_info(excludes,buf+1) ;
  1196.           break ;
  1197.            case '#':        /* comment lines */
  1198.            default:
  1199.           break ;
  1200.            }
  1201.         }
  1202.      }
  1203.       fclose(fp) ;
  1204.       do_filter = TRUE ;
  1205.       }
  1206. }
  1207.  
  1208. /***********************************************/
  1209.  
  1210. int _Cdecl main(argc,argv)
  1211. int argc ;
  1212. char *argv[] ;
  1213. {
  1214.    int lines_per_page = -1 ;
  1215.    int total_lines = -1 ;
  1216.    int use_FF = TRUE ;
  1217.    int last_line ;
  1218.    int body_lines ;
  1219.    char *typeface = NULL ;
  1220.    char *summary_file = NULL ;
  1221.    char *formats_file = NULL ;
  1222.    char *filter_file = NULL ;
  1223.    char *last_page_num ;
  1224.    
  1225.    fputs("INTPRINT v", stderr) ;
  1226.    fputs(VERSION, stderr) ;
  1227.    fputs(" by Ralf Brown and others.  Donated to the Public Domain.\n",stderr) ;
  1228.    if (argc == 1 && isatty(0))
  1229.       usage() ;      /* give help if invoked with no args and keybd input */
  1230.    while (argc >= 2 && argv[1][0] == '-')
  1231.       {
  1232.       switch (argv[1][1])
  1233.      {
  1234.      case 'B':
  1235.         printer_bold = TRUE ;
  1236.         /* fall through to -b */
  1237.      case 'b':
  1238.         boldface = TRUE ;
  1239.         break ;
  1240.      case 'd':
  1241.         duplex = TRUE ;
  1242.         break ;
  1243.      case 'e':
  1244.         indent = 8 ;
  1245.         page_width = 87 ;  /* 96 - indent - 1 right margin */
  1246.         break ;
  1247.      case 'f':
  1248.         formats_file = argv[1]+2 ;
  1249.         break ;
  1250.      case 'F':
  1251.         filter_file = argv[1]+2 ;
  1252.         break ;
  1253.      case 'H':   /* page headers */
  1254.         do_headers = TRUE ;
  1255.         break ;
  1256.      case 'i':
  1257.         indent = atoi(argv[1]+2) ;
  1258.         break ;
  1259.      case 'I':
  1260.         IBM_chars = TRUE ;
  1261.         break ;
  1262.      case 'l':
  1263.         lines_per_page = atoi(argv[1]+2) ;
  1264.         break ;
  1265.      case 'L':
  1266.         total_lines = atoi(argv[1]+2) ;
  1267.         break ;
  1268.      case 'm':
  1269.         multi_file = TRUE ;
  1270.         break ;
  1271.      case 'n':
  1272.         pages_printed = atoi(argv[1]+2) ;
  1273.         break ;
  1274.      case 'P':
  1275.         if (argv[1][2] == '?')
  1276.            display_printers() ;
  1277.         else
  1278.            select_printer(argv[1]+2) ;
  1279.         break ;
  1280.      case 'p':
  1281.         page_numbers = TRUE ;
  1282.         break ;
  1283.      case 'r':
  1284.         first_page = atoi(argv[1]+2) ;
  1285.         last_page_num = strchr(argv[1]+2, ':') ;
  1286.         last_page = last_page_num ? atoi(last_page_num+1) : 0 ;
  1287.         if (last_page == 0)
  1288.            last_page = 9999 ;
  1289.         break ;
  1290.      case 's':
  1291.         summary_file = argv[1]+2 ;
  1292.         break ;
  1293.      case 't':
  1294.         typeface = argv[1]+2 ;
  1295.         break ;
  1296.      case 'w':
  1297.         widow_length = atoi(argv[1]+2) ;
  1298.         break ;
  1299.      case 'x':
  1300.         include_index_lines = TRUE ;
  1301.         break ;
  1302.      default:
  1303.         usage() ;
  1304.      }
  1305.       argv++ ;
  1306.       argc-- ;
  1307.       }
  1308.    if (printer == NULL)
  1309.       select_printer("default") ;
  1310.    /* apply any necessary overrides to parameters */
  1311.    if (printer->indent != -1)
  1312.       indent = printer->indent ;
  1313.    if (lines_per_page <= 0)
  1314.       lines_per_page = printer->lines_per_page ;
  1315.    if (total_lines <= 0)
  1316.       total_lines = printer->page_length ;
  1317.    if (page_width <= 0)
  1318.       page_width = printer->page_width ;
  1319.    if (printer->flag)
  1320.       *(printer->flag) = TRUE ;
  1321.    if (cstrlen(&printer->bold_on) == 0)     /* control sequences for bold? */
  1322.       printer_bold = FALSE ;        /* if not, don't try to use them */
  1323.  
  1324.    /* open the summary file, if any */
  1325.    if (summary_file && *summary_file)
  1326.       if ((summary = fopen(summary_file, pages_printed ? "a":"w")) != NULL)
  1327.      do_summary = TRUE ;
  1328.       else
  1329.      fputs("unable to open summary file\n", stderr) ;
  1330.    /* open the data formats file, if any */
  1331.    if (formats_file && *formats_file)
  1332.       if ((formats = fopen(formats_file, pages_printed ? "a":"w")) != NULL)
  1333.      do_formats = TRUE ;
  1334.       else
  1335.      fputs("unable to open formats file\n", stderr) ;
  1336.    /* initialize filtering data, if specified */
  1337.    if (filter_file && *filter_file)
  1338.       build_filter_lists(filter_file) ;
  1339.    if (total_lines <= lines_per_page)
  1340.       {
  1341.       total_lines = lines_per_page ;
  1342.       use_FF = TRUE ;
  1343.       }
  1344.    else
  1345.       use_FF = FALSE ;
  1346.    if (argc == 2 || argc == 3)
  1347.       {
  1348.       input_file = argv[1] ;
  1349.       infile = fopen(input_file,"r") ;
  1350.       if (infile == NULL)
  1351.      fatal("unable to open input file") ;
  1352.       if (argc == 3)
  1353.      {
  1354.      outfile = fopen(argv[2],(pages_printed?"a":"w")) ;
  1355.      if (outfile == NULL)
  1356.         fatal("unable to open output file") ;
  1357.      }
  1358.       else
  1359.      outfile = stdout ;
  1360.       }
  1361.    else
  1362.       usage() ;
  1363.    if (lines_per_page < 20 || lines_per_page > MAXPAGE)
  1364.       {
  1365.       fputs("Surely you jest!  At least 20 and at most 200 lines per page.\n\n", stderr) ;
  1366.       usage() ;
  1367.       }
  1368.    if (widow_length < 3 || widow_length > lines_per_page / 2)
  1369.       {
  1370.       fputs("Widow lines (-w) must be set to at least 3 and at most one-half of the\n",stderr) ;
  1371.       fputs("page length.  Using default of 10 lines.\n",stderr) ;
  1372.       widow_length = 10 ;
  1373.       }
  1374. #ifdef __TURBOC__
  1375.    setvbuf(infile,NULL,_IOFBF,10240) ;    /* use larger disk buffers */
  1376.    setvbuf(outfile,NULL,_IOFBF,10240) ; /* for better performance */
  1377.    if (do_summary)
  1378.       setvbuf(summary,NULL,_IOFBF,4096) ;
  1379.    if (do_formats)
  1380.       setvbuf(formats,NULL,_IOFBF,4096) ;
  1381. #endif /* __TURBOC__ */
  1382.    /* set up the printer */
  1383.    fputcstr(&printer->init1,outfile) ;
  1384.    fputcstr(&printer->init2,outfile) ;
  1385.    if (printer->set_typeface)
  1386.       (*printer->set_typeface)(outfile,typeface) ;
  1387.    if (duplex)
  1388.       {
  1389.       fputcstr(&printer->duplex_on,outfile) ;
  1390.       if ((pages_printed % 2) == 1)    /* next page odd or even? */
  1391.      fputcstr(&printer->marginl,outfile) ;    /* even */
  1392.       else
  1393.      fputcstr(&printer->marginr,outfile) ;    /* odd */
  1394.       }
  1395.    else
  1396.       fputcstr(&printer->marginc,outfile) ;    /* non-duplex, so center */
  1397.    /* start the summary file */
  1398.    if (do_summary && pages_printed == 0)
  1399.       {          /* create header, but only on first part */
  1400.       /* set up the printer */
  1401.       fputcstr(&printer->init1,summary) ;
  1402.       fputcstr(&printer->init2,summary) ;
  1403.       fputcstr(&printer->marginc,summary) ;
  1404.       indent_line(summary) ;
  1405.       fputs("\t\t\t\tInterrupt Summary\n",summary) ;
  1406.       indent_line(summary) ;
  1407.       fputs("\t\t\t\t", summary) ;
  1408.       (*printer->put_line)(summary,17) ;
  1409.       fputs("\n\n",summary) ;
  1410.       indent_line(summary) ;
  1411.       fputs("INT AH AL", summary) ;
  1412.       if (page_numbers)
  1413.      fputs(" Page", summary) ;
  1414.       fputs("\t\t\tDescription\n", summary) ;
  1415.       indent_line(summary) ;
  1416.       (*printer->put_line)(summary,page_width) ;
  1417.       fputc('\n', summary) ;
  1418.       }
  1419.    /* start the data formats file */
  1420.    if (do_formats && pages_printed == 0)
  1421.       {          /* create header, but only on first part */
  1422.       /* set up the printer */
  1423.       fputcstr(&printer->init1,formats) ;
  1424.       fputcstr(&printer->init2,formats) ;
  1425.       fputcstr(&printer->marginc,formats) ;
  1426.       indent_line(formats) ;
  1427.       fputs("\t\t\tData Structure Formats\n", formats) ;
  1428.       indent_line(formats) ;
  1429.       fputs("\t\t\t", formats) ;
  1430.       (*printer->put_line)(formats,22) ;
  1431.       fputs("\n\n", formats) ;
  1432.       indent_line(formats) ;
  1433.       fputs("INT AH AL", formats) ;
  1434.       if (page_numbers)
  1435.      fputs(" Page", formats) ;
  1436.       fputs("\t\tData Structure\n", formats) ;
  1437.       }
  1438.    if (page_numbers)
  1439.       body_lines = lines_per_page - 2 ;
  1440.    else
  1441.       body_lines = lines_per_page ;
  1442.    if (do_headers)
  1443.       body_lines -= 2 ;
  1444.    last_line = 0 ;
  1445.    while (!feof(infile) && !out_of_files)
  1446.       {
  1447.       fill_buffer(last_line,body_lines) ;
  1448.       last_line = find_page_break(body_lines) ;
  1449.       print_buffer(last_line,lines_per_page,total_lines,use_FF) ;
  1450.       }
  1451.    if (last_line < body_lines)
  1452.       {
  1453.       int i ;
  1454.       
  1455.       for (i = last_line ; i < body_lines ; i++)
  1456.      strcpy(buffer[i-last_line], buffer[i]) ;
  1457.       print_buffer(body_lines-last_line,lines_per_page,total_lines,use_FF) ;
  1458.       }
  1459.    /* reset the printer */
  1460.    fputcstr(&printer->term1,outfile) ;
  1461.    fputcstr(&printer->term2,outfile) ;
  1462.    fflush(outfile) ;
  1463.    itoa(pages_printed, num, 10) ;
  1464.    fputs(num, stderr) ;
  1465.    fputs(" pages\n", stderr) ;
  1466.    if (do_summary)
  1467.       {
  1468.       /* reset the printer */
  1469.       fputcstr(&printer->term1,summary) ;
  1470.       fputcstr(&printer->term2,summary) ;
  1471.       fclose(summary) ;
  1472.       }
  1473.    if (do_formats)
  1474.       {
  1475.       /* reset the printer */
  1476.       fputcstr(&printer->term1,formats) ;
  1477.       fputcstr(&printer->term2,formats) ;
  1478.       fclose(formats) ;
  1479.       }
  1480.    fclose(infile) ;
  1481.    return 0 ;
  1482. }
  1483.